package com.heihei.videopreview;

import com.heihei.constant.MessageConstant;
import com.heihei.imgpreview.GeneratePreviewImg;
import com.heihei.imgpreview.dto.ImgInfoDTO;
import com.heihei.imgpreview.dto.LineDTO;
import com.heihei.util.NumberUtilF;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class CreateVideoPreview implements Runnable{
    private File videoFile;
    private File targetPreviewImgFile;
    private Integer previewImgCount;
    private String threadId;

    public CreateVideoPreview(String threadId, File videoFile, File targetPreviewImgFile, Integer previewImgCount) {
        this.threadId = threadId;
        this.videoFile = videoFile;
        this.targetPreviewImgFile = targetPreviewImgFile;
        this.previewImgCount = previewImgCount;
    }

    public CreateVideoPreview() {
    }
    //    public static void main(String[] args) throws IOException {
////        singleDirMultiVideoRandomPreviewImg(new File("D:\\115_Downloads\\美优 Eva Elfie 大合集 02\\Eva Elfie aka Lady Jay pack 02\\主"), new File("D:\\115_Downloads\\美优 Eva Elfie 大合集 02\\Eva Elfie aka Lady Jay pack 02\\主\\preview"), 16);
////        FileUtilF.handleFiles(new File("D:\\115_Downloads\\美优 Eva Elfie 大合集 02\\Eva Elfie aka Lady Jay pack 02"), file -> {
//////            if(FileUtilF.isVideo(file) && file.getName().endsWith("(1).mp4")) {
//////                file.delete();
//////            }
//////        });
//        File parentDir = new File("D:\\115_Downloads\\美优 Eva Elfie 大合集 02\\Eva Elfie aka Lady Jay pack 02");
//        File[] files = parentDir.listFiles();
//        for (File dir : files) {
//            if(dir.isDirectory()) {
//                singleDirMultiVideoRandomPreviewImg(dir, new File(dir, "preview"), 16);
//            }
//        }
//    }

    @Override
    public void run() {
        try {
            System.out.println("正在处理视频文件：" + videoFile.getAbsolutePath());
            singleVideoRandomPreviewImg(this.videoFile, this.targetPreviewImgFile, this.previewImgCount);
            System.out.println(MessageConstant.CONGRATULATIONS + " 视频处理成功：" + this.videoFile.getAbsolutePath());
        } catch (IOException e) {
            System.out.println(MessageConstant.ERROR_MESSAGE + " 处理视频文件出错：" + this.videoFile.getAbsolutePath());
        } finally {
            //删除 CURRENT_VIDEO_HANDLING_MAP 中的key
            VideoPreviewStart.CURRENT_VIDEO_HANDLING_MAP.remove(this.threadId);
        }
    }

    /**
     * 方法描述: 单个视频，制作预览图
     *
     * @param videoFile
     * @param targetPreviewImgFile
     * @param previewImgCount
     * @Return
     * @throws
     * @author duanhengfei
     * @date 2021年02月13日 10:56:30
     */
    public void singleVideoRandomPreviewImg(File videoFile, File targetPreviewImgFile, int previewImgCount) throws IOException {
//        File videoFile = new File("D:\\115_Downloads\\美优 Eva Elfie 大合集 02\\Eva Elfie aka Lady Jay pack 02\\[Nubiles.net] A Valentines Surprise Lady Jay Feb 6, 2019 (1).mp4");
        List<BufferedImage> bufferImgList = splitVideo(videoFile, previewImgCount);
        write2ImgFile(bufferImgList, targetPreviewImgFile);
    }

    public void write2ImgFile(List<BufferedImage> bufferImgList, File targetPreviewImgFile) throws IOException {
        List<ImgInfoDTO> imgInfoDTOList = GeneratePreviewImg.addImg(bufferImgList);
        List<LineDTO> resultLineDtoList = GeneratePreviewImg.getResultLineDto(imgInfoDTOList);
        GeneratePreviewImg.writeImg(resultLineDtoList, targetPreviewImgFile);
    }

    public List<BufferedImage> splitVideo(File videoFile, int count) {
        List<BufferedImage> imageList = new ArrayList<>();
        FFmpegFrameGrabber frameGrabber = null;
        try {
            frameGrabber = FFmpegFrameGrabber.createDefault(videoFile);
            frameGrabber.start();
            long frameTime = frameGrabber.getLengthInTime() / 1000000;
            int frameLength = frameGrabber.getLengthInFrames();
//            List<Integer> list = random(frameTime, frameLength);
            List<Integer> list = random(frameLength, count);
            for (int i = 0; i < frameLength; i++) {
                Frame frame = frameGrabber.grabImage();
                if (list.contains(i)) {
                    Java2DFrameConverter converter = new Java2DFrameConverter();
                    BufferedImage image = converter.getBufferedImage(frame);
                    imageList.add(image);
                    if(list.get(list.size() - 1) == i) break;
                }
            }
            String logStr = String.format("视频总时长=%ss，总帧数=%s，抽取帧数=%s", frameTime, frameLength, list.size());
            System.out.println(logStr);
            MergeVideoPreviewStart.SB.append(videoFile.getAbsolutePath() + "\r\n" + logStr + "\r\n");
        } catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
        } finally {
            if (frameGrabber != null) {
                try {
                    frameGrabber.stop();
                } catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
                }
            }
        }
        return imageList;
    }

    private List<Integer> random(long frameTime, int frameLength) {
        long count = 200;
        if (frameTime <= 100) {
            count = 10;
        } else if (frameTime <= 1800) {
            count = frameTime / 10;
        }
        List<Integer> list = new ArrayList<Integer>();

        if (frameLength < count) {
            for (int i = 0; i < frameLength; i++) {
                list.add(i);
            }
            return list;
        }

        long range = (frameLength - 5) / count;
        for (long i = range + 5; i < frameLength; i = i + range) {
            int rand = (int) ((i - range) + Math.random() * range);
            list.add(rand);
        }
        return list;
    }

    public List<Integer> random(int frameLength, int count) {
        List<Integer> list = new ArrayList<Integer>();
        if (frameLength < count) {
            for (int i = 0; i < frameLength; i++) {
                list.add(i);
            }
            return list;
        }
        //跳过前五帧
        if(frameLength - 5 < count) {
            for (int i = 5; i < frameLength; i++) {
                list.add(i);
            }
            return list;
        }
        int section = (frameLength - 5) / count;
        Random r = NumberUtilF.getRandom();
        int last = 5;
        for (int i = 0; i < count; i++) {
            list.add(r.nextInt(section) + last);
            last += section;
        }
        return list;
    }
}